package com.df.excel_export.utils;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.enums.CellExtraTypeEnum;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.df.excel_export.common.Constant;
import com.df.excel_export.common.ExcelTableManager;
import com.df.excel_export.common.ExportTask;
import com.df.excel_export.common.ProjectEnums;
import com.df.excel_export.excel.ExcelEnumReadListener;
import com.df.excel_export.excel.ExcelTableHeaderListener;
import com.df.excel_export.excel_table.ExcelSheet;
import com.df.excel_export.excel_table.ExcelTableStructure;
import com.df.excel_export.excel_table.HHeader;
import com.df.excel_export.project_config.ProjectConfig;
import com.df.excel_export.validator.IFieldValidator;
import com.df.excel_export.validator.ValidatorManager;
import com.df.excel_export.web.ExportTaskWebSocket;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

public class ExcelTools {
    public static AtomicBoolean isHanding = new AtomicBoolean(false);
    public static ThreadLocal<List<String>> handleMsgs = new ThreadLocal<>();

    //info级别的消息
    public static void addHandleMsg(String msg) {
        JSONObject respMsg = new JSONObject();
        respMsg.put("id",3);
        JSONObject respData = new JSONObject();
        respData.put("type","config");
        respData.put("log",msg);
        respData.put("level","info");
        respMsg.put("data",respData);
        ExportTaskWebSocket.sendAllMessage(JSON.toJSONString(respMsg));
    }
    public static void addErrorMsg(String msg) {
        //TODO 检查websocket是否有链接用户，有的话推送消息
        JSONObject respMsg = new JSONObject();
        respMsg.put("id",3);
        JSONObject respData = new JSONObject();
        respData.put("type","config");
        respData.put("log",msg);
        respData.put("level","error");
        respMsg.put("data",respData);
        ExportTaskWebSocket.sendAllMessage(JSON.toJSONString(respMsg));
    }
    public static void addExceptionMsg(Exception e) {
        StringBuilder sb = new StringBuilder();
        sb.append(e.toString()+"\n");
        StackTraceElement[] stackTrace = e.getStackTrace();
        for (StackTraceElement traceElement : stackTrace) {
            sb.append("\t"+traceElement.toString());
        }
        ExportTask.logger.error(sb.toString());
    }
    public static void addWarningMsg(String msg) {
        //TODO 检查websocket是否有链接用户，有的话推送消息
        JSONObject respMsg = new JSONObject();
        respMsg.put("id",3);
        JSONObject respData = new JSONObject();
        respData.put("type","config");
        respData.put("log",msg);
        respData.put("level","warning");
        respMsg.put("data",respData);
        ExportTaskWebSocket.sendAllMessage(JSON.toJSONString(respMsg));
    }
    public static void respTaskFinish() {
        //TODO 检查websocket是否有链接用户，有的话推送消息
        JSONObject respMsg = new JSONObject();
        respMsg.put("id",2);
        JSONObject respData = new JSONObject();
        respData.put("type","config");
        respData.put("status",2);
        respMsg.put("data",respData);
        ExportTaskWebSocket.sendAllMessage(JSON.toJSONString(respMsg));
//        List<String> strings = handleMsgs.get();
//        if (strings == null) {
//            return;
//        }
//        strings.add(msg);
    }

    public static void parseTableEnum(String fileName,ProjectConfig cfg) {
        if(!fileName.endsWith(".xlsx") && !fileName.endsWith(".xls")){
            ExportTask.logger.error("枚举文件不是excel表格！解析失败");
            ExportTask.nowTask.interrupt();
            return;
        }
        File file = new File(fileName);
        if (!file.exists()) {
            ExportTask.logger.error("要处理的枚举文件不存在：" + fileName);
            ExportTask.nowTask.interrupt();
            return;
        }
        if (!file.canRead()) {
            ExportTask.logger.error("要处理的枚举文件不可读，放弃处理：" + fileName);
            ExportTask.nowTask.interrupt();
            return;
        }

        ExcelReader reader = EasyExcel.read(fileName).build();
        List<ReadSheet> readSheets = reader.excelExecutor().sheetList();
        List<ReadSheet> enumSheets = readSheets.stream().filter(readSheet -> readSheet.getSheetName().startsWith("enum")).collect(Collectors.toList());
        if(enumSheets.isEmpty()){
            ExportTask.logger.warn("枚举配置文件里没有找到名为enum的表格，放弃处理：" + fileName);
            ExportTask.nowTask.interrupt();
            return;
        }
        ProjectEnums enums = ExcelTableManager.projectEnums.get(fileName);
        enums.getEnums().clear();
        enums.setLastModify(0L);
        for (ReadSheet enumSheet : enumSheets) {
            try {
                enumSheet.setHeadRowNumber(0);
                //是enum表和数据表，先处理枚举，因为表格里的类型会用到枚举
                enumSheet.getCustomReadListenerList().add(new ExcelEnumReadListener(cfg));
                reader.read(enumSheet);
                if(!ExportTask.canContinue()){
                    break;
                }
            } catch (Exception e) {
                ExportTask.logger.error(e.getMessage());
                ExportTask.nowTask.interrupt();
                e.printStackTrace();
                break;
            }
        }
        if(ExportTask.canContinue()){
            enums.setLastModify(file.lastModified());
            ExcelTableManager.saveProjectEnum(cfg.getName(), enums);
        }
    }


    /**
     * 解析表的rule，构建解析器和分析依赖
     *
     * @param toParse
     * @param baseConfig
     */
    public static void parseTableRule(List<ExcelTableStructure> toParse, ProjectConfig baseConfig){
        if (toParse == null || toParse.isEmpty()) {
            return;
        }
        for (ExcelTableStructure excelTable : toParse) {
            doParseTableRule(excelTable, baseConfig);
        }
    }

    private static void doParseTableRule(ExcelTableStructure excelTable, ProjectConfig projectConfig) {
        ExcelSheet table = excelTable.getTable();
        String type = table.getType();
        if(type.equals(Constant.TableType.Vertical)){//TODO 竖表暂时不解析依赖
            return;
        }
        List<HHeader> hHeaders = table.getHHeaders();
        excelTable.getDepends().clear();
        out:
        for (HHeader hHeader : hHeaders) {
            if(!hHeader.getValidatorList().isEmpty()){
                for (IFieldValidator validator : hHeader.getValidatorList()) {
                    //排除自己
                    List<String> collect = validator.getDepends().stream().filter(name -> !table.getTableName().equals(name)).collect(Collectors.toList());
                    excelTable.getDepends().addAll(collect);
                }
                continue;
            }
            hHeader.getValidatorList().clear();

            List<String> fieldRules = hHeader.getValidators();
            List<IFieldValidator> validators = new ArrayList<>();
            for (String fieldRule : fieldRules) {
                try {
                    IFieldValidator validator = ValidatorManager.parseValidator(hHeader.getType(), fieldRule);
                    if (validator != null) {
                        validators.add(validator);
                        if (!validator.getDepends().isEmpty()) {
                            //排除自己
                            List<String> collect = validator.getDepends().stream().filter(name -> !table.getTableName().equals(name)).collect(Collectors.toList());
                            excelTable.getDepends().addAll(collect);
                        }
                    }else {
                        ExportTask.logger.warn("未支持的校验字符串："+fieldRule+" 文件名："+excelTable.getMeta().getFilePath()+" 所在列："+hHeader.getCol());
                    }
                } catch (Exception e) {
                    ExportTask.nowTask.setCanContinue(false);
                    ExportTask.logger.error("规则表达式解析错误！文件名：" + excelTable.getMeta().getFilePath() + "; sheet名：" + table.getSheetName() + "; 列名：" + hHeader.getEnName() + "; rule表达式：" + fieldRule + ";错误：" + e.getMessage());
                    break out;
                }

            }
            if(ExportTask.canContinue()){
                hHeader.getValidatorList().addAll(validators);
            }
        }


    }

    public static ExcelTableStructure parseTableHeader(File file, ProjectConfig projectConfig) {

        if (!file.canRead()) {
            ExportTask.logger.error("要处理的文件不可读，放弃处理：" + file.getAbsolutePath());
            return null;
        }
        ExcelTableStructure structure = new ExcelTableStructure();
        ExcelReader reader = EasyExcel.read(file.getAbsolutePath()).extraRead(CellExtraTypeEnum.COMMENT).build();
        List<ReadSheet> readSheets = reader.excelExecutor().sheetList();
        for (ReadSheet readSheet : readSheets) {
            try {
                String sheetName = readSheet.getSheetName();
                readSheet.setHeadRowNumber(0);
                //包含前缀和后缀为数据表,且只读第一个sheet
                if (sheetName.startsWith(projectConfig.getTable_prefix()) && sheetName.endsWith(projectConfig.getTable_suffix())) {
                    readSheet.getCustomReadListenerList().add(new ExcelTableHeaderListener(structure,projectConfig));
                    reader.read(readSheet);
                    break;
                }
            } catch (Exception e) {
                ExportTask.logger.error(e.getMessage());
                e.printStackTrace();
            }
        }
        if(structure.isParserDone()){
            return structure;
        }else {
            return null;
        }
    }
}
